package com.tms.utils.token.impl;

import com.tms.domain.User;
import com.tms.security.entity.UserDetail;
import com.tms.service.UserService;
import com.tms.utils.token.TokenService;
import io.jsonwebtoken.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.Authentication;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletRequest;
import javax.xml.bind.DatatypeConverter;
import java.util.Date;
import java.util.Objects;

@Service
public class TokenServiceImpl implements TokenService {

    @Autowired
    private UserService userService;

    private static String SECRET = "qwerasdfdxzvdfajjlkjeiojznvxndjkfaowijeiodl";

    private static final String authorization = "Authorization";

    private static final String split = " ";

    /**
     * 根据user对象指定token
     *
     * @param user
     * @return
     */
    @Override
    public String getToken(User user) {

        SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256;
        //创建时间
        long nowMillis = System.currentTimeMillis();
        Date now = new Date(nowMillis);
        long currentTime = nowMillis + (long) 30 * 24 * 60 * 60 * 1000;
        //暂时设置为一个月的时间
        Date end = new Date(currentTime);
        //我们将使用我们的Api Key秘密签署您的JWT
        JwtBuilder builder = Jwts.builder()
                .setIssuedAt(now)
                .setExpiration(end)
                .setAudience(user.getNo())
                .claim("position", user.getPosition().getName())
                .claim("password", user.getPwd())
                .claim("workcell", user.getWorkcell().getId())
                .signWith(signatureAlgorithm, SECRET);
        return builder.compact();
    }

    /**
     * 取出token里的信息
     *
     * @param token
     * @return
     */
    @Override
    public Claims getClaims(String token) {
        Claims claims = null;
        try {
            claims = Jwts.parser().setSigningKey(DatatypeConverter.parseBase64Binary(SECRET)).parseClaimsJws(token).getBody();
        } catch (ExpiredJwtException eje) {
            System.out.println("===== Token过期 =====" + eje.getMessage());
        } catch (SignatureException e) {
            System.out.println(e.getMessage());
        }
        return claims;
    }

    /**
     * 从request里取token,得到no后查找返回user
     *
     * @param request http请求
     * @return user对象
     */
    @Override
    public User getUserByRequest(HttpServletRequest request) {
        String header = request.getHeader(authorization);
        int spiltSize = 2;
        if (header == null || header.length() == 0 || header.split(split).length != spiltSize) {
            return null;
        }
        String token = header.split(split)[1];
        return getUserByToken(token);
    }

    /**
     * 直接通过request取出对应的workcellId
     *
     * @param request
     * @return
     */
    @Override
    public int getWorkcellId(HttpServletRequest request) {
        String token = request.getHeader(authorization).split(split)[1];
        return getWorkcellId(token);
    }

    /**
     * 直接通过request取出对应的position
     *
     * @param request
     * @return
     */
    @Override
    public String getPosition(HttpServletRequest request) {
        String token = request.getHeader(authorization).split(split)[1];
        //从request里取得token失败；
        if (token == null || Objects.equals(token, "")) {
            return null;
        }
        Claims claims = getClaims(token);
        if (claims == null) {
            return null;
        }
        return (String) claims.get("position");
    }

    /**
     * 判断token是否过期
     *
     * @param token token
     * @return 过期返回false
     */
    @Override
    public boolean isExpiration(String token) {
        return getClaims(token).getExpiration().before(new Date());
    }

    /**
     * 根据user对象指定token
     *
     * @param authentication au
     * @return
     */
    @Override
    public String getTokenFromAuthentication(Authentication authentication) {
        SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256;
        //创建时间
        long nowMillis = System.currentTimeMillis();
        Date now = new Date(nowMillis);
        long currentTime = nowMillis + (long) 30 * 24 * 60 * 60 * 1000;
        //暂时设置为一个月的时间
        Date end = new Date(currentTime);
        UserDetail userDetail = (UserDetail) authentication.getPrincipal();

        //我们将使用我们的Api Key秘密签署您的JWT
        JwtBuilder builder = Jwts.builder()
                .setIssuedAt(now)
                .setExpiration(end)
                .setAudience(userDetail.getNo())
                .claim("position", userDetail.getPosition().getName())
                .claim("password", userDetail.getPassword())
                .claim("workcell", userDetail.getWorkcell().getId())
                .signWith(signatureAlgorithm, SECRET);
        return builder.compact();
    }

    /**
     * 根据原有token进行刷新
     *
     * @param token
     * @return
     */
    @Override
    public String refresh(String token) {
        token = token.split(" ")[1];
        if (isExpiration(token)) {
            return null;
        }
        User user = getUserByToken(token);
        return getToken(user);
    }

    /**
     * 从token里取得信息找到user
     *
     * @param token
     * @return
     */
    @Override
    public User getUserByToken(String token) {
        //从request里取得token失败；
        if (token == null || Objects.equals(token, "")) {
            return null;
        }
        Claims claims = getClaims(token);
        if (claims == null) {
            return null;
        }
        String no = claims.getAudience();
        return userService.findUserByNoAndWorkcell(no, getWorkcellId(token));
    }

    /**
     * 取得workcellId
     *
     * @param token
     * @return
     */
    @Override
    public int getWorkcellId(String token) {
        if (token == null || Objects.equals(token, "")) {
            return Integer.parseInt(null);
        }
        Claims claims = getClaims(token);
        if (claims == null) {
            return Integer.parseInt(null);
        }
        return (Integer) claims.get("workcell");
    }
}
